#!/usr/bin/python3
"""
Create an isolinux bootloader

"""

import os
import shutil
import sys
import string
import osbuild.api


SCHEMA_2 = """
"options": {
  "additionalProperties": false,
  "required": ["product", "kernel"],
  "properties": {
    "product": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "version"],
      "properties": {
        "name": {"type": "string"},
        "version": {"type": "string"}
       }
    },
    "kernel": {
      "type": "object",
      "required": ["dir"],
      "properties": {
        "dir": {
          "type": "string"
        },
        "opts": {
          "description": "Array of group names for this user",
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }
},
"inputs": {
  "type": "object",
  "additionalProperties": false,
  "required": ["data"],
  "properties": {
    "data": {
      "type": "object",
      "additionalProperties": true
    }
  }
}
"""


# The isolinux configuration template
ISOLINUX_CFG_TEMPLATE = """
default vesamenu.c32
timeout 600

display boot.msg

# Clear the screen when exiting the menu, instead of leaving the menu displayed.
# For vesamenu, this means the graphical background is still displayed without
# the menu itself for as long as the screen remains in graphics mode.
menu clear
menu background splash.png
menu title ${product} ${version}
menu vshift 8
menu rows 18
menu margin 8
#menu hidden
menu helpmsgrow 15
menu tabmsgrow 13

# Border Area
menu color border * #00000000 #00000000 none

# Selected item
menu color sel 0 #ffffffff #00000000 none

# Title bar
menu color title 0 #ff7ba3d0 #00000000 none

# Press [Tab] message
menu color tabmsg 0 #ff3a6496 #00000000 none

# Unselected menu item
menu color unsel 0 #84b8ffff #00000000 none

# Selected hotkey
menu color hotsel 0 #84b8ffff #00000000 none

# Unselected hotkey
menu color hotkey 0 #ffffffff #00000000 none

# Help text
menu color help 0 #ffffffff #00000000 none

# A scrollbar of some type? Not sure.
menu color scrollbar 0 #ffffffff #ff355594 none

# Timeout msg
menu color timeout 0 #ffffffff #00000000 none
menu color timeout_msg 0 #ffffffff #00000000 none

# Command prompt text
menu color cmdmark 0 #84b8ffff #00000000 none
menu color cmdline 0 #ffffffff #00000000 none

# Do not display the actual menu unless the user presses a key. All that is displayed is a timeout message.

menu tabmsg Press Tab for full configuration options on menu items.

menu separator # insert an empty line
menu separator # insert an empty line

label linux
  menu label ^Install ${product} ${version}
  kernel vmlinuz
  append initrd=initrd.img ${cmdline} quiet

label check
  menu label Test this ^media & install ${product} ${version}
  menu default
  kernel vmlinuz
  append initrd=initrd.img ${cmdline} rd.live.check quiet

menu separator # insert an empty line

# utilities submenu
menu begin ^Troubleshooting
  menu title Troubleshooting ${product} ${version}

label basic
  menu indent count 5
  menu label Install using ^basic graphics mode
  text help
	Try this option out if you're having trouble installing
	${product} ${version}.
  endtext
  kernel vmlinuz
  append initrd=initrd.img ${cmdline} nomodeset quiet
label rescue
  menu indent count 5
  menu label ^Rescue a ${product} system
  text help
	If the system will not boot, this lets you access files
	and edit config files to try to get it booting again.
  endtext
  kernel vmlinuz
  append initrd=initrd.img ${cmdline} inst.rescue quiet
label memtest
  menu label Run a ^memory test
  text help
	If your system is having issues, a problem with your
	system's memory may be the cause. Use this utility to
	see if the memory is working correctly.
  endtext
  kernel memtest

menu separator # insert an empty line

label local
  menu label Boot from ^local drive
  localboot 0xffff

menu separator # insert an empty line
menu separator # insert an empty line

label returntomain
  menu label Return to ^main menu
  menu exit

"""


def install(src, dst, mode=None):
    shutil.copyfile(src, dst)
    if mode:
        os.chmod(dst, mode)


def main(tree, inputs, options):
    name = options["product"]["name"]
    version = options["product"]["version"]

    kdir = options["kernel"]["dir"]
    kopts = options["kernel"].get("opts")
    debug = options.get("debug", False)

    data = inputs["data"]["path"]

    kerneldir = os.path.join(tree, kdir.lstrip("/"))

    isolinux = os.path.join(tree, "isolinux")
    os.makedirs(isolinux)

    src = os.path.join(data, "usr/share/anaconda/boot/syslinux-splash.png")
    dst = os.path.join(isolinux, "splash.png")
    install(src, dst)

    isolinuxfiles = [("isolinux.bin", 0o755),
                     ("ldlinux.c32", 0o755),
                     ("libcom32.c32", 0o755),
                     ("libutil.c32", 0o755),
                     ("vesamenu.c32", 0o755)]

    for target, mode in isolinuxfiles:
        src = os.path.join(data, "usr/share/syslinux/", target)
        dst = os.path.join(isolinux, target)
        install(src, dst, mode)

    if debug:
        src = os.path.join(data, "usr/share/syslinux/isolinux-debug.bin")
        dst = os.path.join(isolinux, "isolinux.bin")
        install(src, dst, 0o755)

    tplt = string.Template(ISOLINUX_CFG_TEMPLATE)
    data = tplt.safe_substitute({
        "version": version,
        "product": name,
        "cmdline": " ".join(kopts)
    })

    config = os.path.join(isolinux, "isolinux.cfg")
    with open(config, "w") as cfg:
        cfg.write(data)

    # link the kernel
    os.link(os.path.join(kerneldir, "vmlinuz"),
            os.path.join(isolinux, "vmlinuz"))
    os.link(os.path.join(kerneldir, "initrd.img"),
            os.path.join(isolinux, "initrd.img"))


if __name__ == '__main__':
    args = osbuild.api.arguments()
    ret = main(args["tree"], args["inputs"], args["options"])
    sys.exit(ret)
